package forecasting.converter.parser;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;

import forecasting.converter.DiscreteValue;
import forecasting.converter.FeatureType;
import forecasting.converter.RealValue;
import forecasting.converter.UnknownValue;


public class WekaDatasetParser extends AbstractDatasetParserTemplate {
	
	private static final boolean SAVE_CATEGORIES_FOR_DISCRETE_VALUES = true;
	
	public WekaDatasetParser(final boolean saveCategories) {
		super(saveCategories);
	}
	
	/**
	 * @param args
	 * @return TODO
	 */
	public static void main(String[] args) {
		// validate input parameters
		if(args.length != 2) {
			System.out.println(args.length);
			System.out.println("Converter <file name> <output file name minus externsion>");
			System.exit(-1);
		}
		
		final String inputFileName = args[0];
		final String outputFileName = args[1];
			
		final WekaDatasetParser parser = new WekaDatasetParser(SAVE_CATEGORIES_FOR_DISCRETE_VALUES);
		parser.run(inputFileName, outputFileName);
		System.out.println("finished!");
	}

	/**
	 * {@inheritDoc}
	 */
	protected void createOutputFile(final ArrayList<FeatureType> labels, final String inputFileName, final String outputFileName) {
		// second pass where we attach labels to each column
		PrintWriter outfile = null;
		try {
			outfile = new PrintWriter(outputFileName + ".arff");
		} catch (FileNotFoundException e) {
			System.out.println(e);
			e.printStackTrace();
		}
		
		outfile.println("@Relation firstRun");
		for(int i = 0; i < labels.size(); i++) {
			if (labels.get(i) instanceof UnknownValue) {
				// do nothing
			} else {
				if(labels.get(i).toString().equals("@Attribute "))
					System.err.println("Label only and not null!!");
				outfile.println(labels.get(i));
			}
		}
		
		outfile.println("@Data");
		// load file 
		final Scanner scan = openFileScanner(inputFileName);
		
		skipFirstLine(scan);
		int sampleNum = 0;
		// create the rest of the weka dataset file
		while (scan.hasNext()) {
			++sampleNum;
			
			final String line = scan.nextLine();
			
			// checking for empty rows in the input dataset.
			if (line.length() == 0) {
				continue;
			}
			
			final String[] featureVector = line.substring(0, line.length() - 1).split("\t",-1);
			
			// validating that we're receiving the correct number of columns
			// FIXME: We are adding one to the validated vector size because intrain.txt has 841 columns
			//if (featureVector.length != (AbstractDatasetParserTemplate.EXPECTED_FEATURE_VECTOR_SIZE + 2)) {
			//	System.err.println("Unexpected number of columns for sample # " + sampleNum + ", column size = " + featureVector.length);
			//	System.exit(-1);
			//}
			
			printFeatureVector(labels, outfile, featureVector);
		}
		
		outfile.close();
	}

	private void skipFirstLine(final Scanner scan) {
		if(scan.hasNext())
			scan.nextLine();
	}
	
	private void printFeatureVector(ArrayList<FeatureType> labels,
			PrintWriter outfile, String[] featureVector) {
		boolean isFirst = true, wroteValue = false;
		for (int i = 0; i < labels.size(); i++) {
			if (labels.get(i) != null && !(labels.get(i) instanceof UnknownValue)) {
				
				// If this is the first column, we don't print a comma
				if (!isFirst) {
					outfile.print(",");
				} else {
					isFirst = false;
				}
				
				// check if the column exists
				if (featureVector[i].isEmpty()) {
					// column does not exist. weka expects a "?" in this case.
					outfile.print("?"); wroteValue = true;
				} else {
					if(labels.get(i) instanceof DiscreteValue)
						outfile.print("\""  + DiscreteValue.replaceQuotes(featureVector[i]) + "\"");
					else if(labels.get(i) instanceof RealValue)
						outfile.print(RealValue.convertToDouble(featureVector[i]));
					else
						outfile.print(featureVector[i]);
					wroteValue = true;
				}
			}
		}
		if(wroteValue)
			outfile.println();
	}
}
